/*
Copyright (C) 1996-1997 Id Software, Inc.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 3
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/

// to do - add callback function
#include "quakedef.h"

QSTATEFILTER *d3d_State = NULL;

ID3D10DepthStencilState *d3d_ZmodeNormal = NULL;
ID3D10DepthStencilState *d3d_ZmodeNowrite = NULL;
ID3D10DepthStencilState *d3d_ZmodeNone = NULL;

ID3D10BlendState *d3d_BlendNone = NULL;
ID3D10BlendState *d3d_BlendAdditive = NULL;
ID3D10BlendState *d3d_BlendMultiply = NULL;
ID3D10BlendState *d3d_BlendMax = NULL;
ID3D10BlendState *d3d_BlendMin = NULL;
ID3D10BlendState *d3d_BlendAlpha = NULL;
ID3D10BlendState *d3d_BlendZFill = NULL;

ID3D10SamplerState *d3d_SamplerSurface = NULL;
ID3D10SamplerState *d3d_SamplerMesh = NULL;
ID3D10SamplerState *d3d_SamplerLightmap = NULL;
ID3D10SamplerState *d3d_SamplerDraw2D = NULL;
ID3D10SamplerState *d3d_SamplerShadow = NULL;
ID3D10SamplerState *d3d_SamplerPoint = NULL;

ID3D10RasterizerState *d3d_RasterizerDefault = NULL;
ID3D10RasterizerState *d3d_RasterizerFlipCull = NULL;

class CD3DStateHandler : public CD3DHandler
{
public:
	ID3D10DepthStencilState *CreateDepthStencilState (BOOL zenable, D3D10_DEPTH_WRITE_MASK writemask, D3D10_COMPARISON_FUNC depthfunc)
	{
		ID3D10DepthStencilState *dss = NULL;

		D3D10_DEPTH_STENCIL_DESC desc = {
			zenable,
			writemask,
			depthfunc,
			FALSE,
			D3D10_DEFAULT_STENCIL_READ_MASK,
			D3D10_DEFAULT_STENCIL_WRITE_MASK,
			{D3D10_STENCIL_OP_KEEP, D3D10_STENCIL_OP_KEEP, D3D10_STENCIL_OP_KEEP, D3D10_COMPARISON_ALWAYS},
			{D3D10_STENCIL_OP_KEEP, D3D10_STENCIL_OP_KEEP, D3D10_STENCIL_OP_KEEP, D3D10_COMPARISON_ALWAYS}
		};

		d3d_Device->CreateDepthStencilState (&desc, &dss);
		return dss;
	}

	ID3D10BlendState *CreateBlendState (BOOL enable, D3D10_BLEND src, D3D10_BLEND dst, D3D10_BLEND_OP op, int colorwrite = 15)
	{
		ID3D10BlendState *bs = NULL;

		D3D10_BLEND_DESC desc = {
			FALSE,
			{enable, enable, enable, enable, enable, enable, enable, enable},
			src,
			dst,
			op,
			src,
			dst,
			op,
			{colorwrite, colorwrite, colorwrite, colorwrite, colorwrite, colorwrite, colorwrite, colorwrite}
		};

		d3d_Device->CreateBlendState (&desc, &bs);
		return bs;
	}

	ID3D10SamplerState *CreateSamplerState (D3D10_FILTER filter, D3D10_TEXTURE_ADDRESS_MODE address, BOOL mipmap)
	{
		ID3D10SamplerState *ss = NULL;

		D3D10_SAMPLER_DESC desc = {
			filter,
			address,
			address,
			address,
			0.0f,
			1,
			D3D10_COMPARISON_ALWAYS,
			{0, 0, 0, 0},
			0.0f,
			mipmap ? D3D10_FLOAT32_MAX : 0.0f
		};

		d3d_Device->CreateSamplerState (&desc, &ss);
		return ss;
	}

public:
	void OnCreateDevice (void)
	{
		// create the state filtering object
		if (!d3d_State) d3d_State = new QSTATEFILTER ();

		d3d_ZmodeNormal = this->CreateDepthStencilState (TRUE, D3D10_DEPTH_WRITE_MASK_ALL, D3D10_COMPARISON_LESS_EQUAL);
		d3d_ZmodeNowrite = this->CreateDepthStencilState (TRUE, D3D10_DEPTH_WRITE_MASK_ZERO, D3D10_COMPARISON_LESS_EQUAL);
		d3d_ZmodeNone = this->CreateDepthStencilState (FALSE, D3D10_DEPTH_WRITE_MASK_ZERO, D3D10_COMPARISON_ALWAYS);

		d3d_BlendNone = this->CreateBlendState (FALSE, D3D10_BLEND_ONE, D3D10_BLEND_ZERO, D3D10_BLEND_OP_ADD);
		d3d_BlendAdditive = this->CreateBlendState (TRUE, D3D10_BLEND_ONE, D3D10_BLEND_ONE, D3D10_BLEND_OP_ADD);
		d3d_BlendMultiply = this->CreateBlendState (TRUE, D3D10_BLEND_SRC_COLOR, D3D10_BLEND_ZERO, D3D10_BLEND_OP_ADD);
		d3d_BlendMax = this->CreateBlendState (TRUE, D3D10_BLEND_ONE, D3D10_BLEND_ONE, D3D10_BLEND_OP_MAX);
		d3d_BlendMin = this->CreateBlendState (TRUE, D3D10_BLEND_ONE, D3D10_BLEND_ONE, D3D10_BLEND_OP_MIN);
		d3d_BlendAlpha = this->CreateBlendState (TRUE, D3D10_BLEND_SRC_ALPHA, D3D10_BLEND_INV_SRC_ALPHA, D3D10_BLEND_OP_ADD);
		d3d_BlendZFill = this->CreateBlendState (FALSE, D3D10_BLEND_ZERO, D3D10_BLEND_ZERO, D3D10_BLEND_OP_ADD, 0);

		d3d_SamplerSurface = this->CreateSamplerState (D3D10_FILTER_MIN_MAG_MIP_LINEAR, D3D10_TEXTURE_ADDRESS_WRAP, TRUE);
		d3d_SamplerMesh = this->CreateSamplerState (D3D10_FILTER_MIN_MAG_MIP_LINEAR, D3D10_TEXTURE_ADDRESS_CLAMP, TRUE);
		d3d_SamplerDraw2D = this->CreateSamplerState (D3D10_FILTER_MIN_MAG_MIP_LINEAR, D3D10_TEXTURE_ADDRESS_WRAP, FALSE);
		d3d_SamplerLightmap = this->CreateSamplerState (D3D10_FILTER_MIN_MAG_MIP_LINEAR, D3D10_TEXTURE_ADDRESS_CLAMP, FALSE);
		d3d_SamplerPoint = this->CreateSamplerState (D3D10_FILTER_MIN_MAG_MIP_POINT, D3D10_TEXTURE_ADDRESS_CLAMP, FALSE);

		// create a default rasterizer state
		D3D10_RASTERIZER_DESC desc;

		desc.FillMode = D3D10_FILL_SOLID;
		desc.CullMode = D3D10_CULL_FRONT;
		desc.FrontCounterClockwise = TRUE;
		desc.DepthBias = 0;
		desc.DepthBiasClamp = 0;
		desc.SlopeScaledDepthBias = 0;
		desc.DepthClipEnable = TRUE;
		desc.ScissorEnable = FALSE;
		desc.MultisampleEnable = FALSE;
		desc.AntialiasedLineEnable = FALSE;

		d3d_Device->CreateRasterizerState (&desc, &d3d_RasterizerDefault);

		// flip the backface culling mode so that mdls don't self-shadow
		desc.CullMode = D3D10_CULL_BACK;
		d3d_Device->CreateRasterizerState (&desc, &d3d_RasterizerFlipCull);

		// create the shadowmap sampler state
		D3D10_SAMPLER_DESC sdesc = {
			D3D10_FILTER_COMPARISON_MIN_MAG_MIP_LINEAR,
			D3D10_TEXTURE_ADDRESS_CLAMP,
			D3D10_TEXTURE_ADDRESS_CLAMP,
			D3D10_TEXTURE_ADDRESS_CLAMP,
			0.0f,
			1,
			D3D10_COMPARISON_LESS,
			{0, 0, 0, 0},
			0.0f,
			0.0f
		};

		d3d_Device->CreateSamplerState (&sdesc, &d3d_SamplerShadow);
	}

	void OnReleaseDevice (void)
	{
		SAFE_RELEASE (d3d_ZmodeNormal);
		SAFE_RELEASE (d3d_ZmodeNowrite);
		SAFE_RELEASE (d3d_ZmodeNone);

		SAFE_RELEASE (d3d_BlendNone);
		SAFE_RELEASE (d3d_BlendAdditive);
		SAFE_RELEASE (d3d_BlendMultiply);
		SAFE_RELEASE (d3d_BlendMax);
		SAFE_RELEASE (d3d_BlendMin);
		SAFE_RELEASE (d3d_BlendAlpha);
		SAFE_RELEASE (d3d_BlendZFill);

		SAFE_RELEASE (d3d_SamplerSurface);
		SAFE_RELEASE (d3d_SamplerMesh);
		SAFE_RELEASE (d3d_SamplerLightmap);
		SAFE_RELEASE (d3d_SamplerDraw2D);
		SAFE_RELEASE (d3d_SamplerShadow);

		SAFE_RELEASE (d3d_RasterizerDefault);
		SAFE_RELEASE (d3d_RasterizerFlipCull);
	}

	void OnModeChange (void)
	{
		d3d_State->ClearState ();

		ID3D10SamplerState *samplers[] = {
			d3d_SamplerDraw2D,
			d3d_SamplerSurface,
			d3d_SamplerLightmap,
			d3d_SamplerMesh,
			d3d_SamplerShadow,
			d3d_SamplerPoint
		};

		// bind our samplers to dedicated slots once-only
		d3d_Device->PSSetSamplers (0, sizeof (samplers) / sizeof (samplers[0]), samplers);
	}

	void OnBeginFrame (void)
	{
		d3d_Device->RSSetState (d3d_RasterizerDefault);
	}
} d3d_StateHandler;


renderstate_t rs_default = {BM_NONE, ZM_NORMAL};
renderstate_t rs_additive = {BM_ADDITIVE, ZM_NOWRITE};
renderstate_t rs_lumablend = {BM_MAX, ZM_NOWRITE};
renderstate_t rs_drawblended = {BM_ALPHA, ZM_NONE};
renderstate_t rs_drawnoblend = {BM_NONE, ZM_NONE};
renderstate_t rs_alphablend = {BM_ALPHA, ZM_NOWRITE};


QSTATEFILTER::QSTATEFILTER (void)
{
	// set as very first item so that any subsequent state change can trigger it safely
	this->OnStateChange = QSTATEFILTER::NoStateChangeCallback;
	this->ClearState ();
}


void QSTATEFILTER::ClearState (void)
{
	this->SetStateChangeCallback ();

	this->BlendState = NULL;
	this->DepthState = NULL;

	// this needs to be set to a value that's impossible for a *real* stencil ref so that it
	// will force an update first time it's seen
	this->StencilRef = 0xffffffff;

	for (int i = 0; i < 128; i++)
	{
		this->VSTextures[i] = NULL;
		this->GSTextures[i] = NULL;
		this->PSTextures[i] = NULL;
	}

	this->InputLayout = NULL;
	this->VertexShader = NULL;
	this->GeometryShader = NULL;
	this->PixelShader = NULL;
}

void QSTATEFILTER::SetStateChangeCallback (xcommand_t cbfunc)
{
	this->OnStateChange = cbfunc;
}


/*
QSTATEFILTER::QSTATEFILTER (void)
{
	// set as very first item so that any subsequent state change can trigger it safely
	this->OnStateChange = QSTATEFILTER::NoStateChangeCallback;

	// vertex streams
	for (int i = 0; i < 16; i++)
	{
		d3d_Device->GetStreamSource (
			i, 
			&this->VertexStream[i].Buffer,
			&this->VertexStream[i].Offset,
			&this->VertexStream[i].Stride
		);

		d3d_Device->GetStreamSourceFreq (
			i,
			&this->VertexStream[i].Freq
		);
	}

	d3d_Device->GetVertexDeclaration (&this->VertexDeclaration);
	d3d_Device->GetIndices (&this->IndexBuffer);

	// render states
	// cheesy hack to force an update first time it's seen
	for (int i = 0; i < 256; i++)
		this->RenderState[i] = D3DRS_FORCE_DWORD;

	for (int i = 0; i < 16; i++)
	{
		d3d_Device->GetTexture (i, &this->PSCurrentTexture[i]);

		d3d_Device->GetSamplerState (i, D3DSAMP_MINFILTER, (DWORD *) &this->PSSamplerState[i].MinFilter);
		d3d_Device->GetSamplerState (i, D3DSAMP_MAGFILTER, (DWORD *) &this->PSSamplerState[i].MagFilter);
		d3d_Device->GetSamplerState (i, D3DSAMP_MIPFILTER, (DWORD *) &this->PSSamplerState[i].MipFilter);
		d3d_Device->GetSamplerState (i, D3DSAMP_MAXANISOTROPY, &this->PSSamplerState[i].Anisotropy);

		// cheesy hack to force an update first time it's seen
		this->PSSamplerState[i].AddressMode = D3DTADDRESS_FORCE_DWORD;
	}

	this->VertexShader = NULL;
	this->PixelShader = NULL;
	this->NewRenderState = NULL;

	// set states to their documented defaults to protect us against bad drivers
	this->SetRenderState (D3DRS_ZENABLE, D3DZB_FALSE);
	this->SetRenderState (D3DRS_FILLMODE, D3DFILL_SOLID);
	this->SetRenderState (D3DRS_SHADEMODE, D3DSHADE_FLAT);
	this->SetRenderState (D3DRS_ZWRITEENABLE, FALSE);
	this->SetRenderState (D3DRS_ALPHATESTENABLE, FALSE);
	this->SetRenderState (D3DRS_LASTPIXEL, TRUE);
	this->SetRenderState (D3DRS_SRCBLEND, D3DBLEND_ONE);
	this->SetRenderState (D3DRS_DESTBLEND, D3DBLEND_ZERO);
	this->SetRenderState (D3DRS_CULLMODE, D3DCULL_CCW);
	this->SetRenderState (D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
	this->SetRenderState (D3DRS_ALPHAREF, 0);
	this->SetRenderState (D3DRS_ALPHAFUNC, D3DCMP_ALWAYS);
	this->SetRenderState (D3DRS_ALPHABLENDENABLE, FALSE);
	this->SetRenderState (D3DRS_FOGENABLE, FALSE);
	this->SetRenderState (D3DRS_SPECULARENABLE, FALSE);
	this->SetRenderState (D3DRS_FOGCOLOR, 0);
	this->SetRenderState (D3DRS_FOGTABLEMODE, D3DFOG_NONE);
	this->SetRenderStatef (D3DRS_FOGSTART, 0.0f);
	this->SetRenderStatef (D3DRS_FOGEND, 1.0f);
	this->SetRenderStatef (D3DRS_FOGDENSITY, 1.0f);
	this->SetRenderState (D3DRS_RANGEFOGENABLE, FALSE);
	this->SetRenderState (D3DRS_STENCILENABLE, FALSE);
	this->SetRenderState (D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP);
	this->SetRenderState (D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP);
	this->SetRenderState (D3DRS_STENCILPASS, D3DSTENCILOP_KEEP);
	this->SetRenderState (D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
	this->SetRenderState (D3DRS_STENCILREF, 0);
	this->SetRenderState (D3DRS_STENCILMASK, 0xffffffff);
	this->SetRenderState (D3DRS_STENCILWRITEMASK, 0xffffffff);
	this->SetRenderState (D3DRS_TEXTUREFACTOR, 0xffffffff);
	this->SetRenderState (D3DRS_WRAP0, 0);
	this->SetRenderState (D3DRS_WRAP1, 0);
	this->SetRenderState (D3DRS_WRAP2, 0);
	this->SetRenderState (D3DRS_WRAP3, 0);
	this->SetRenderState (D3DRS_WRAP4, 0);
	this->SetRenderState (D3DRS_WRAP5, 0);
	this->SetRenderState (D3DRS_WRAP6, 0);
	this->SetRenderState (D3DRS_WRAP7, 0);
	this->SetRenderState (D3DRS_CLIPPING, TRUE);
	this->SetRenderState (D3DRS_LIGHTING, FALSE);
	this->SetRenderState (D3DRS_FOGVERTEXMODE, D3DFOG_NONE);
	this->SetRenderState (D3DRS_COLORVERTEX, TRUE);
	this->SetRenderState (D3DRS_LOCALVIEWER, TRUE);
	this->SetRenderState (D3DRS_NORMALIZENORMALS, FALSE);
	this->SetRenderState (D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1);
	this->SetRenderState (D3DRS_SPECULARMATERIALSOURCE, D3DMCS_COLOR2);
	this->SetRenderState (D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL);
	this->SetRenderState (D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_MATERIAL);
	this->SetRenderState (D3DRS_CLIPPLANEENABLE, 0);
	this->SetRenderStatef (D3DRS_POINTSIZE_MIN, 1.0f);
	this->SetRenderState (D3DRS_POINTSPRITEENABLE, FALSE);
	this->SetRenderState (D3DRS_MULTISAMPLEANTIALIAS, FALSE);
	this->SetRenderState (D3DRS_MULTISAMPLEMASK, 0xffffffff);
	this->SetRenderState (D3DRS_PATCHEDGESTYLE, D3DPATCHEDGE_DISCRETE);
	this->SetRenderStatef (D3DRS_POINTSIZE_MAX, 1.0f);
	this->SetRenderState (D3DRS_COLORWRITEENABLE, 0x0000000f);
	this->SetRenderState (D3DRS_BLENDOP, D3DBLENDOP_ADD);
	this->SetRenderState (D3DRS_POSITIONDEGREE, D3DDEGREE_CUBIC);
	this->SetRenderState (D3DRS_NORMALDEGREE, D3DDEGREE_LINEAR);
	this->SetRenderState (D3DRS_SCISSORTESTENABLE, FALSE);
	this->SetRenderStatef (D3DRS_SLOPESCALEDEPTHBIAS, 0.0f);
	this->SetRenderStatef (D3DRS_MINTESSELLATIONLEVEL, 1.0f);
	this->SetRenderStatef (D3DRS_MAXTESSELLATIONLEVEL, 1.0f);
	this->SetRenderStatef (D3DRS_ADAPTIVETESS_X, 0.0f);
	this->SetRenderStatef (D3DRS_ADAPTIVETESS_Y, 0.0f);
	this->SetRenderStatef (D3DRS_ADAPTIVETESS_Z, 1.0f);
	this->SetRenderStatef (D3DRS_ADAPTIVETESS_W, 0.0f);
	this->SetRenderState (D3DRS_ENABLEADAPTIVETESSELLATION, FALSE);
	this->SetRenderState (D3DRS_TWOSIDEDSTENCILMODE, FALSE);
	this->SetRenderState (D3DRS_CCW_STENCILFAIL, D3DSTENCILOP_KEEP);
	this->SetRenderState (D3DRS_CCW_STENCILZFAIL, D3DSTENCILOP_KEEP);
	this->SetRenderState (D3DRS_CCW_STENCILPASS, D3DSTENCILOP_KEEP);
	this->SetRenderState (D3DRS_CCW_STENCILFUNC, D3DCMP_ALWAYS);
	this->SetRenderState (D3DRS_COLORWRITEENABLE1, 0x0000000f);
	this->SetRenderState (D3DRS_COLORWRITEENABLE2, 0x0000000f);
	this->SetRenderState (D3DRS_COLORWRITEENABLE3, 0x0000000f);
	this->SetRenderState (D3DRS_BLENDFACTOR, 0xffffffff);
	this->SetRenderState (D3DRS_SRGBWRITEENABLE, 0);
	this->SetRenderStatef (D3DRS_DEPTHBIAS, 0.0f);
	this->SetRenderState (D3DRS_WRAP8, 0);
	this->SetRenderState (D3DRS_WRAP9, 0);
	this->SetRenderState (D3DRS_WRAP10, 0);
	this->SetRenderState (D3DRS_WRAP11, 0);
	this->SetRenderState (D3DRS_WRAP12, 0);
	this->SetRenderState (D3DRS_WRAP13, 0);
	this->SetRenderState (D3DRS_WRAP14, 0);
	this->SetRenderState (D3DRS_WRAP15, 0);
	this->SetRenderState (D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
	this->SetRenderState (D3DRS_SRCBLENDALPHA, D3DBLEND_ONE);
	this->SetRenderState (D3DRS_DESTBLENDALPHA, D3DBLEND_ZERO);
	this->SetRenderState (D3DRS_BLENDOPALPHA, D3DBLENDOP_ADD);
	this->SetRenderState (D3DRS_DITHERENABLE, FALSE);
	this->SetRenderState (D3DRS_VERTEXBLEND, D3DVBF_DISABLE);
	this->SetRenderStatef (D3DRS_POINTSIZE, 1.0f);
	this->SetRenderState (D3DRS_POINTSCALEENABLE, FALSE);
	this->SetRenderStatef (D3DRS_POINTSCALE_A, 1.0f);
	this->SetRenderStatef (D3DRS_POINTSCALE_B, 0.0f);
	this->SetRenderStatef (D3DRS_POINTSCALE_C, 0.0f);
	this->SetRenderState (D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE);
	this->SetRenderStatef (D3DRS_TWEENFACTOR, 0.0f);
	this->SetRenderState (D3DRS_ANTIALIASEDLINEENABLE, FALSE);
}


void QSTATEFILTER::SetStateChangeCallback (xcommand_t cbfunc)
{
	this->OnStateChange = cbfunc;
}


void QSTATEFILTER::UnbindStreams (void)
{
	for (int i = 0; i < 16; i++)
		this->SetStreamSource (i);

	this->SetIndices ();
}


void QSTATEFILTER::UnbindState (void)
{
	this->SetStateChangeCallback ();
	this->UnbindStreams ();

	for (int i = 0; i < 16; i++) this->PSSetTexture (i);

	this->VSSetLayout ();
	this->VSSetShader ();
	this->PSSetShader ();
}


void QSTATEFILTER::SetRenderState (renderstate_t *rs)
{
	if (this->NewRenderState == rs) return;

	// choose the correct alpha blending mode
	switch (rs->blend)
	{
	case BM_MULTIPLY:
		this->SetRenderState (D3DRS_ALPHABLENDENABLE, TRUE);
		this->SetRenderState (D3DRS_SRCBLEND, D3DBLEND_DESTCOLOR);
		this->SetRenderState (D3DRS_DESTBLEND, D3DBLEND_ZERO);
		this->SetRenderState (D3DRS_BLENDOP, D3DBLENDOP_ADD);
		break;

	case BM_ALPHA:
		this->SetRenderState (D3DRS_ALPHABLENDENABLE, TRUE);
		this->SetRenderState (D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
		this->SetRenderState (D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
		this->SetRenderState (D3DRS_BLENDOP, D3DBLENDOP_ADD);
		break;

	case BM_ADDITIVE:
		this->SetRenderState (D3DRS_ALPHABLENDENABLE, TRUE);
		this->SetRenderState (D3DRS_SRCBLEND, D3DBLEND_ONE);
		this->SetRenderState (D3DRS_DESTBLEND, D3DBLEND_ONE);
		this->SetRenderState (D3DRS_BLENDOP, D3DBLENDOP_ADD);
		break;

	case BM_MAX:
		this->SetRenderState (D3DRS_ALPHABLENDENABLE, TRUE);
		this->SetRenderState (D3DRS_SRCBLEND, D3DBLEND_ONE);
		this->SetRenderState (D3DRS_DESTBLEND, D3DBLEND_ONE);
		this->SetRenderState (D3DRS_BLENDOP, D3DBLENDOP_MAX);
		break;

	case BM_NONE:
	default:
		this->SetRenderState (D3DRS_ALPHABLENDENABLE, FALSE);
		break;
	}

	// choose the correct z test mode
	if (rs->zmode == ZM_NORMAL || rs->zmode == ZM_NOWRITE)
	{
		if (r_draworder->value)
			this->SetRenderState (D3DRS_ZFUNC, D3DCMP_GREATEREQUAL);
		else this->SetRenderState (D3DRS_ZFUNC, D3DCMP_LESSEQUAL);

		this->SetRenderState (D3DRS_ZENABLE, D3DZB_TRUE);
	}
	else this->SetRenderState (D3DRS_ZENABLE, D3DZB_FALSE);

	// choose the correct z write mode
	if (rs->zmode == ZM_NORMAL)
		this->SetRenderState (D3DRS_ZWRITEENABLE, TRUE);
	else this->SetRenderState (D3DRS_ZWRITEENABLE, FALSE);

	// handle everything else
	if (gl_cull->value)
		this->SetRenderState (D3DRS_CULLMODE, D3DCULL_CCW);
	else this->SetRenderState (D3DRS_CULLMODE, D3DCULL_NONE);

	this->NewRenderState = rs;
}


void QSTATEFILTER::PSSetSampler (DWORD Stage, D3DTEXTUREFILTERTYPE MinMagFilter, D3DTEXTUREFILTERTYPE MipFilter, D3DTEXTUREADDRESS AddressMode, DWORD Anisotropy)
{
	if (Anisotropy > d3d_DeviceCaps.MaxAnisotropy) Anisotropy = d3d_DeviceCaps.MaxAnisotropy;

	// check first so that we can switch the filter for anisotropic
	if (this->PSSamplerState[Stage].MagFilter != MinMagFilter)
	{
		this->OnStateChange ();
		d3d_Device->SetSamplerState (Stage, D3DSAMP_MAGFILTER, MinMagFilter);
		this->PSSamplerState[Stage].MagFilter = MinMagFilter;
	}

	// now switch the filter for anisotropic
	if (Anisotropy > 1)
		MinMagFilter = D3DTEXF_ANISOTROPIC;
	else Anisotropy = 1;

	// and now do the min filter
	if (this->PSSamplerState[Stage].MinFilter != MinMagFilter)
	{
		this->OnStateChange ();
		d3d_Device->SetSamplerState (Stage, D3DSAMP_MINFILTER, MinMagFilter);
		this->PSSamplerState[Stage].MinFilter = MinMagFilter;
	}

	if (this->PSSamplerState[Stage].MipFilter != MipFilter)
	{
		this->OnStateChange ();
		d3d_Device->SetSamplerState (Stage, D3DSAMP_MIPFILTER, MipFilter);
		this->PSSamplerState[Stage].MipFilter = MipFilter;
	}

	if (this->PSSamplerState[Stage].AddressMode != AddressMode)
	{
		this->OnStateChange ();
		d3d_Device->SetSamplerState (Stage, D3DSAMP_ADDRESSU, AddressMode);
		d3d_Device->SetSamplerState (Stage, D3DSAMP_ADDRESSV, AddressMode);
		d3d_Device->SetSamplerState (Stage, D3DSAMP_ADDRESSW, AddressMode);
		this->PSSamplerState[Stage].AddressMode = AddressMode;
	}

	if (this->PSSamplerState[Stage].Anisotropy != Anisotropy)
	{
		this->OnStateChange ();
		d3d_Device->SetSamplerState (Stage, D3DSAMP_MAXANISOTROPY, Anisotropy);
		this->PSSamplerState[Stage].Anisotropy = Anisotropy;
	}
}
*/
